package com.duoo.pag.pag

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.view.View

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
import org.libpag.PAGImageView
import org.libpag.PAGView
import com.duoo.pag.pag.ninepatch.NinePatchViewFactory

/** PagPlugin */
class PagPlugin : FlutterPlugin, MethodCallHandler {

    private lateinit var channel: MethodChannel

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "pag")
        channel.setMethodCallHandler(this)
        flutterPluginBinding.platformViewRegistry.registerViewFactory(
            "plugins/pag",
            PagFactory(flutterPluginBinding.binaryMessenger)
        )
        flutterPluginBinding.platformViewRegistry.registerViewFactory(
            "nine_patch_flutter_view", NinePatchViewFactory(flutterPluginBinding.binaryMessenger)
        )

    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        if (call.method == "getPlatformVersion") {
            result.success("Android ${android.os.Build.VERSION.RELEASE}")
        } else {
            result.notImplemented()
        }
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }
}

class PagFactory(private val binaryMessenger: BinaryMessenger) :
    PlatformViewFactory(StandardMessageCodec.INSTANCE) {
    override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
        val data = args as Map<*, *>
        if (data["viewType"] == 1) {
            return PagImageView(context, viewId, args, binaryMessenger)
        }
        return PagView(context, viewId, args, binaryMessenger)
    }

}

class PagView(
    private val context: Context,
    viewId: Int,
    args: Any?,
    binaryMessenger: BinaryMessenger,
) : PlatformView, MethodChannel.MethodCallHandler, PAGView.PAGViewListener {
    private val pagView: PAGView = PAGView(context)
    private var methodChannel: MethodChannel?
    private var isDispose = false

    init {
        pagView.addListener(this)
        val data = args as Map<*, *>
        val url = data["url"]
        val assetName = data["assetName"]
        val repeatCount = data["repeatCount"]
        val autoPlay = data["autoPlay"]
        methodChannel = MethodChannel(binaryMessenger, "plugins/pag_$viewId")
        methodChannel?.setMethodCallHandler(this)
        if (url != null) {
            pagView.setPathAsync(url.toString()) {
                if (autoPlay == true) {
                    pagView.play()
                }
            }
        }
        if (assetName != null) {
            pagView.setPathAsync("assets://flutter_assets/$assetName") {
                if (autoPlay == true) {
                    if (!isDispose) {
                        pagView.play()
                    }
                }
            }
        }
        if (repeatCount != null) {
            pagView.setRepeatCount(repeatCount as Int)
        }
        if (autoPlay == true) {
            if (!isDispose) {
                pagView.play()
            }
        }
        methodChannel?.invokeMethod("onInit", null)

    }

    override fun getView(): View {
        return pagView
    }

    override fun dispose() {
        isDispose = true
        methodChannel?.setMethodCallHandler(null)
        methodChannel = null
        pagView.pause()
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        when (call.method) {
            "start" -> {
                pagView.play()
            }

            "stop" -> {
                pagView.pause()
            }
        }
    }

    override fun onAnimationStart(p0: PAGView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationStart", null)
        }
    }

    override fun onAnimationEnd(p0: PAGView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationEnd", null)
        }

    }

    override fun onAnimationCancel(p0: PAGView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationCancel", null)
        }
    }

    override fun onAnimationRepeat(p0: PAGView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationRepeat", null)
        }
    }

    override fun onAnimationUpdate(p0: PAGView?) {
    }

}

class PagImageView(
    private val context: Context,
    viewId: Int,
    args: Any?,
    binaryMessenger: BinaryMessenger,
) : PlatformView, MethodChannel.MethodCallHandler, PAGImageView.PAGImageViewListener {
    private val pagView: PAGImageView = PAGImageView(context)
    private var methodChannel: MethodChannel?
    private var isDispose = false

    init {
        pagView.addListener(this)
        val data = args as Map<*, *>
        val url = data["url"]
        val assetName = data["assetName"]
        val repeatCount = data["repeatCount"]
        val autoPlay = data["autoPlay"]
        methodChannel = MethodChannel(binaryMessenger, "plugins/pag_$viewId")
        methodChannel?.setMethodCallHandler(this)
        if (url != null) {
            pagView.setPathAsync(url.toString()) {
                if (autoPlay == true) {
                    pagView.play()
                }
            }
        }
        if (assetName != null) {
            pagView.setPathAsync("assets://flutter_assets/$assetName") {
                if (autoPlay == true) {
                    if (!isDispose) {
                        pagView.play()
                    }
                }
            }
        }
        if (repeatCount != null) {
            pagView.setRepeatCount(repeatCount as Int)
        }
        if (autoPlay == true) {
            if (!isDispose) {
                pagView.play()
            }
        }
        methodChannel?.invokeMethod("onInit", null)

    }

    override fun getView(): View {
        return pagView
    }

    override fun dispose() {
        isDispose = true
        methodChannel?.setMethodCallHandler(null)
        methodChannel = null
        pagView.pause()
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        when (call.method) {
            "start" -> {
                pagView.play()
            }

            "stop" -> {
                pagView.pause()
            }
        }
    }

    override fun onAnimationStart(p0: PAGImageView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationStart", null)
        }
    }

    override fun onAnimationEnd(p0: PAGImageView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationEnd", null)
        }

    }

    override fun onAnimationCancel(p0: PAGImageView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationCancel", null)
        }
    }

    override fun onAnimationRepeat(p0: PAGImageView?) {
        Handler(Looper.getMainLooper()).post {
            methodChannel?.invokeMethod("onAnimationRepeat", null)
        }
    }

    override fun onAnimationUpdate(p0: PAGImageView?) {
    }

}
